/* Copyright (c) 2008 Erik Beeson
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted
 * provided that the following conditions are met:
 *
 * Redistributions of source code must retain the
 *     above copyright notice, this list of conditions
 *     and the following disclaimer.
 * Redistributions in binary form must reproduce the
 *     above copyright notice, this list of conditions
 *     and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 * Neither the name of Erik Beeson nor YourSharade nor the
 *     names of its contributors may be used to endorse or
 *     promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.restly.core;

import org.restly.Resource;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Aug 29, 2008, 4:22:59 PM
 *
 * @author <a href="http://restly.org/">Erik Beeson</a>
 */
public class ResourceInfo {
	private static final Pattern PATTERN_ATTRIBUTES = Pattern.compile("\\{([\\w_]+)\\}");

	private final Class clazz;
	private final Pattern pattern;

	private final List<String> attributeNames;


	@SuppressWarnings("unchecked")
	public ResourceInfo(Class clazz) {
		this(clazz, ((Resource) clazz.getAnnotation(Resource.class)).value());
	}

	public ResourceInfo(Class clazz, String path) {
		this.clazz = clazz;
		this.attributeNames = parseAttributeNames(path);
		this.pattern = makePattern(path);
	}

	public static List<String> parseAttributeNames(String path) {
		path = path.replaceAll("/*$", "");
		List<String> attributeNames = new ArrayList<String>();
		Matcher m = PATTERN_ATTRIBUTES.matcher(path);
		while(m.find()) {
			attributeNames.add(m.group(1));
		}
		return attributeNames;
	}

	public static Pattern makePattern(String path) {
		path = path.replaceAll("/*$", "");
		return Pattern.compile(PATTERN_ATTRIBUTES.matcher(path).replaceAll("([\\\\w_-]+)"));
	}

	public Map<String, String> matches(String path) {
		path = path.replaceAll("/*$", "");

		Matcher matcher = pattern.matcher(path);

		if(matcher.matches()) {
			Map<String, String> attributes = new HashMap<String, String>();
			Iterator<String> it = attributeNames.iterator();
			for(int i = 1; i <= matcher.groupCount() && it.hasNext(); i++) {
				attributes.put(it.next(), matcher.group(i));
			}
			return attributes;
		} else {
			return null;
		}
	}

	public Class getClazz() {
		return clazz;
	}

	public String toString() {
		return new StringBuffer().append(this.getClass().getSimpleName())
				.append("[class=").append(clazz)
				.append(",pattern=").append(pattern)
				.append(",attributeNames=").append(attributeNames)
				.append("]")
				.toString();
	}
}